package jp.seraph.cui;

import java.util.List;

import jp.seraph.cui.message.MessageUtil;

import org.apache.commons.lang.NullArgumentException;

public class CuiSystemUtil {
    private CuiSystemUtil() {

    }

    /**
     * 現在のModeと与えられたPathから、SystemNodeを特定し、返します。
     *
     * @param aCurrent
     * @param aPath
     * @return
     */
    public static SystemNode resolvePath(ConsoleContext aCurrent, String aPath, String aSeparator) throws IllegalArgumentException {
        if (aCurrent == null)
            throw new NullArgumentException("aCurrent");
        if (aPath == null)
            throw new NullArgumentException("aPath");
        if (aSeparator == null)
            throw new NullArgumentException("aSeparator");

        String tSeparator = aSeparator;
        Mode tCurrent = aCurrent.getMode();

        // フルパス指定のときはそこだけを探す
        if (aPath.startsWith(aSeparator))
            return resolvePath(getRoot(tCurrent), aPath, tSeparator);

        // それ以外はPathとして登録されているModeから相対を探す
        String tFullPath;
        List<Mode> tPathes = aCurrent.getPath();
        StringBuilder tBuilder = new StringBuilder();

        for (Mode tMode : tPathes) {
            tFullPath = getFullPath(tMode, aSeparator);
            tBuilder.append(tFullPath);
            tBuilder.append(";");

            tFullPath += aPath;

            try{
                return resolvePath(getRoot(tMode), tFullPath, aSeparator);
            }catch(IllegalArgumentException e){
                // 見つからなかったら次のPathをチェック
                // 例外でやるのはきもいなぁ……
            }
        }

        throw new IllegalArgumentException(MessageUtil.resolvePathError(tBuilder.toString(), aPath));
    }

    private static SystemNode resolvePath(SystemNode tRootNode, String aFullPath, String aSeparator) {
        SystemNode tNode = tRootNode;

        // ここの２か所の同じ例外の書き方がきもい…　１つにまとめたい
        String[] tPathes = aFullPath.split(aSeparator);
        for (String tMember : tPathes) {
            if (tMember.equals(""))
                continue;

            if (!tNode.getType().isMode())
                throw new IllegalArgumentException(MessageUtil.resolvePathError(aFullPath, tMember));

            tNode = ((Mode) tNode).goTo(tMember);

            if (tNode == null)
                throw new IllegalArgumentException(MessageUtil.resolvePathError(aFullPath, tMember));
        }

        return tNode;
    }

    /**
     * 引数のSystemNodeのフルパスを文字列で得ます
     *
     * @param aNode
     * @return
     */
    public static String getFullPath(SystemNode aNode, String aSeparator) {
        if (aNode == null)
            throw new NullArgumentException("aNode");
        if (aSeparator == null)
            throw new NullArgumentException("aSeparator");

        String tPath = "";
        if (aNode.getType().isMode())
            tPath = aSeparator;

        tPath = aNode.getName() + tPath;

        if (aNode.isRoot())
            return tPath;

        return getFullPath(aNode.getParent(), aSeparator) + tPath;
    }

    public static SystemNode getRoot(SystemNode aNode) {
        if (aNode.isRoot())
            return aNode;

        return getRoot(aNode.getParent());
    }
    
    public static String getPathSeparator(){
        return "/";
    }
}
